<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            justify-content: space-between;
        }
        #grid1, #grid2{
            display: grid;
            margin: 0 auto;
            grid-gap: 6px;
            grid-template-columns: repeat(4, 1fr);
            align-content: start;
        }
        .item{
            height: 100px;
            width: 100px;
            border-radius: 10px;
            box-shadow: 1px 1px 8px 0px #e2e3f1;
            padding: 10px;
            background-color: palegoldenrod;
        }
        .ani-diagonal {
            animation: ani-diagonal .6s ease-in-out calc(var(--stagger) * 60ms) both;
        }
        .ani-diagonal-infinite {
            /* animation: name duration timing-function delay iteration-count direction fill-mode; */
            animation: ani-diagonal .6s ease-in-out calc(var(--stagger) * 120ms) infinite alternate both;
        }
        @keyframes ani-diagonal {
            from {
                opacity: 0;
                transform: scale(0.6);
            }
            to {
                opacity: 1;
                transform: scale(1);
            }
        }
    </style>
</head>
<body>
    <div id="grid1">
        <div class="item">0</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
        <div class="item">11</div>
        <div class="item">12</div>
        <div class="item">13</div>
        <div class="item">14</div>
        <div class="item">15</div>
        <div class="item">16</div>
        <div class="item">17</div>
        <div class="item">18</div>
        <div class="item">19</div>
        <div class="item">20</div>
        <div class="item">21</div>
        <div class="item">22</div>
        <div class="item">23</div>
    </div>
    <div id="grid2" style="transform: scale(.5);transform-origin: 50% 0;">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
    <script>
        // https://css-tricks.com/different-approaches-for-creating-a-staggered-animation/
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(() => {
                diagonalAni(document.querySelectorAll('#grid1 .item'), 4, 'ani-diagonal');
                diagonalAni(document.querySelectorAll('#grid2 .item'), 4, 'ani-diagonal-infinite')
            }, 16);
            function diagonalAni(els, colNum, aniName) {
                const len = els.length;
                [...els].forEach((el, i) => {
                //  const colNum = (i % colNum) + 1;
                //  const rowNum = Math.ceil((i + 1)/colNum);
                    const colIndex = i % colNum;
                    const rowIndex = Math.ceil((i + 1)/colNum) - 1;
                    el.classList.add(aniName);
                    // 垂直于对角线的（行索引+列索引）值相同
                    el.style.setProperty('--stagger', colIndex + rowIndex);
                });
            }
        })
    </script>
</body>
</html>